/*
 * archivoDirecto.h
 *
 *  Created on: Oct 16, 2012
 *      Author: Federico
 *
 * Para  las  el  archivo  de  frases,  se  deberán  utilizar  un  archivo  directo  de  registros
 * de  longitud  variable con  dispersión  extensible  F((n)i,  (autor(apellido,  (nombre)?)?,  frase),
 * con  n  entero  grande  sin  signo con valor aleatorio  y autor y frase cadenas de longitud
 * variable prefijadas por su longitud (máxima de 255 caracteres).
 *
 * Operaciones a implementar en la Dispersión Extensible:
 *	o Incorporar un registro (n, autor, frase)
 *	o Eliminar un registro con identificador n (sin liberación de bloques)
 *	o Modificar un registro (n, autor, frase)
 * 	o Listar el contenido del archivo en un archivo de texto, con una línea de encabezado para cada bloque
 *
 */

#ifndef ARCHIVODIRECTO_H_
#define ARCHIVODIRECTO_H_

#include <string>
#include <iostream>
#include <memory>

#include "HashRecord.h"
#include "HashBucket.h"
#include "HashFile.h"

using namespace std;

typedef size_t HashIdex;

enum ArchivoDirectoExceptions
{
    RECORD_NUMBER_IS_INVALID, RECORD_IS_NOT_UNIQUE
};

/*
 * Archivo directo de frases
 */

class ArchivoDirecto
{
private:

    HashFile m_archivo;
    HashBucket::BucketID *m_cubetas;
    HashIdex m_tamanioDelHash;
    HashBucket::TypeTD m_tdMasAlto;

    bucket_ptr getNewBucket( HashBucket::TypeTD );
    bucket_ptr cargarCubeta( HashBucket::BucketID nroCubeta );
    bool grabarCubeta( HashBucket::BucketID nroCubeta );
    void partirCubeta( HashIdex indice );
    void reHashearCubetas( bucket_ptr viejaCubeta, HashIdex viejoIndice,
            bucket_ptr nueva, HashIdex nuevoIndice );
    void imprimirCubeta( bucket_ptr &cubeta );

    HashIdex calcularIndice( RecordID n );
    void incrementarHash();
    void reducirHash();
    void partirHash( HashIdex indice );

//	void 		    agregarRegistro( bucket_ptr &cubeta, RecordID id, const string autor, const string frase );
    void imprimirRegistro( HashRecord *registro );

public:
    ArchivoDirecto(const string &filePath, unsigned int blkSize = 0, bool trunc =
            false );
    ~ArchivoDirecto();

// 	ABM
    bool addRecord( RecordID n, const string &autorName,
            const string &autorLastName, const string &phrase );
    void modificarRegistro( RecordID n, const string &autor,
            const string &frase );
    void removeRecord( RecordID n );
    void listarContenido();

//	setters & getters

    unsigned int getNroCubetas() const
    {
        return m_tamanioDelHash;
    }
};

#endif /* ARCHIVODIRECTO_H_ */
